package pratice.learn.flow;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;

import java.io.*;
import java.util.List;

/**
 * 学习流程定义
 * @author 吴宇亮 on 2019/5/10 0010 下午 5:02
 */
public class ProcessDef {

    //根据activiti的配置文件获取流程引擎
    public final static ProcessEngine processEngine = ProcessEngineConfiguration
            .createProcessEngineConfigurationFromResource("activiti/activiti.cfg.xml")
            .buildProcessEngine();

    /**
     * 定义流程 + 部署流程
     */
    @Test
    public void deployment(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()
//                .addClasspathResource("activiti/HelloWorld.bpmn")
//                .addClasspathResource("activiti/HelloWorld.png")
                .addClasspathResource("activiti/template/LeaveBill.bpmn")
                .addClasspathResource("activiti/template/LeaveBill.png")
                .deploy();
    }

    /**
     * 启动流程
     */
    public void start(){
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance helloWorld = runtimeService.startProcessInstanceByKey("HelloWorld");
    }

    /**
     * 查询流程
     */
    @Test
    public void list(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        List<Deployment> list = repositoryService.createDeploymentQuery().list();

        list.forEach(System.out::print);
    }

    /**
     * 删除某一次部署
     */
    @Test
    public void delete(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        String deploymentId = "1";

        //只删除流程定义，如果该流程定义在runtime里面有数据，会报错（因为有外键关联约束）
//        repositoryService.deleteDeployment(deploymentId);

        //先删除runtime里面的数据，在删除流程定义表，确保不会因为外键关联而报错
        repositoryService.deleteDeployment(deploymentId, true);
    }

    /**
     * 查看流程图
     */
    @Test
    public void viewProcessPic(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        String processDefinitionId = "HelloWorld:1:5004";

        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);

        File file = new File("D:/" + processDefinition.getName() + ".png");
        try (
            InputStream processDiagram = repositoryService.getProcessDiagram(processDefinitionId);
            OutputStream os = new FileOutputStream(file);
        ){
            int length = 0;
            byte[] b = new byte[1024];
            while(-1 != (length = processDiagram.read(b))){
                os.write(b, 0, length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //进阶API：查询最新的流程定义
    @Test
    public void listLatest(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .latestVersion()
                .list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition);
        }
    }

    //进阶API：根据流程的key删除所有该版本的流程

    /**
     * 如果某一次部署，部署了两个流程，那就有问题了
     */
    @Test
    public void deleteFlowByKey(){
        RepositoryService repositoryService = processEngine.getRepositoryService();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("HelloWorld")
                .list();
    }

}


















